let handlingCount = 0; // 正在处理的请求数
const puppeteer = require("puppeteer");
const dayjs = require("dayjs");
const fs = require("fs");
const path = require("path");
const Stream = require("stream");

/**
 * 初始化浏览器
 * @returns
 */
async function launchBrowser() {
  try {
    let global = {}; // 全局数据
    //初始化浏览器
    const browser = await puppeteer.launch({
      // executablePath: "/opt/google/chrome-linux/chrome-wrapper", //linux系统chrome浏览器位置
      headless: false, //是否开启无头浏览器模式，默认开启;设置为fasle可以打开浏览器窗口模式调试
      /* args: ['--no-sandbox', '--disable-setuid-sandbox', '--enable-accelerated-2d-canvas', '--enable-aggressive-domstorage-flushing'], */
      //浏览器参数配置
      args: [
        "-disable-gpu",
        "-disable-dev-shm-usage",
        "-disable-setuid-sandbox",
        "-no-first-run",
        "-no-sandbox",
        "-no-zygote",
        // "-single-process",
        "--disable-features=site-per-process",
      ],
      devtools: false, //是否打开浏览器的调试工具
      ignoreHTTPSErrors: true, //是否忽略https
      timeout: 120000,
    });
    //获取用于连接到此 browser 的 WebSocket URL。
    const wsAddress = browser.wsEndpoint();
    //转换链接地址未Buffer
    const w_data = Buffer.from(wsAddress);
    global.wsa = w_data;
    global.browser = browser;
    global.puppeteer = puppeteer;
    console.log("chrome内核启动成功");
    return global;
  } catch (e) {
    console.log(e);
  }
}

/**
 * 打开一个新的窗口
 * @param {*} global 全局参数
 * @param global.wsa 用于连接到此 browser 的 WebSocket URL。
 * @returns
 */
async function getNewPage(global) {
  const browser = await global.puppeteer.connect({
    browserWSEndpoint: global.wsa,
  });
  console.log("open Page");
  return browser.newPage();
}

async function eventHandler(ctx) {
  try {
    // 解析查询参数
    const headers = ctx.header;
    console.log("请求头参数", headers); // 解析查询参数
    const queryParams = ctx.query; //解析get请求url参数
    const token = headers.authorization?.split(" ")[1]; //从请求头获取当前请求的token
    console.log("get请求链接参数==》", queryParams);
    const launchBrowser = await ctx.launchBrowser; //浏览器缓存参数
    if (!queryParams.url) {
      ctx.body = {
        data: null,
        status: 500,
        message: "导出页面链接不能为空",
      };
    }
    // 连接数 + 1
    ++handlingCount;
    console.log(`正在处理的连接数${handlingCount}`);
    // let pageUrl1 = extractDomainWithProtocol(decodeURIComponent(queryParams.url));
    let pageUrl1 = headers.origin;

    // 未超过最大连接数，进行生成
    if (handlingCount <= 5) {
      const startTime = dayjs(); // 打印开始时间
      const page = await getNewPage(launchBrowser); // 开启一个新的标签页
      await page.goto(pageUrl1, {
        waitUntil: ["load", "networkidle0"],
        timeout: 120000,
      }); // 等待响应加载
      // await page.evaluate(function () {
      //   return new Promise((resolve) => {
      //     // 通过递归来滚动页面
      //     function scrollPage() {
      //       // { 浏览器窗口可视区域的高度，页面的总高度，已滚动的高度 }
      //       const { clientHeight, scrollHeight, scrollTop } = document.documentElement;
      //       // 如果滚动高度 + 视口高度 < 总高度，则继续滚动，否则就任务滚动到底部了
      //       if (scrollTop + clientHeight < scrollHeight) {
      //         document.documentElement.scrollTo(0, scrollTop + clientHeight);
      //         // 加一个 setTimeout 来保证滚动的稳定性
      //         setTimeout(() => {
      //           scrollPage();
      //         }, 500);
      //       } else {
      //         resolve();
      //       }
      //     }
      //     scrollPage();
      //   });
      // });
      // 设置Token
      if (token) {
        await page.evaluate((token) => {
          localStorage.setItem(
            "ASSISTANT_LOGIN_INFO",
            JSON.stringify({ accessToken: token })
          );
        }, token);
      }
      page.close();
      const page2 = await getNewPage(launchBrowser); // 开启一个新的标签页
      await page2.goto(decodeURIComponent(queryParams.url), {
        timeout: 120000,
        waitUntil: ["load", "networkidle0"],
      }); // 等待响应加载
      // 页头模板， 详情查看 http://puppeteerjs.com/#?product=Puppeteer&version=v19.2.2&show=api-pagepdfoptions
      const header = `
        <div style="width:calc(100% - 28px);margin-top: -20px; height:40px; border-bottom:1px solid #c9c9c9; display: flex;align-items: center;justify-content: flex-end;">
          <span style="color: #999999; font-size: 14px;"> ${
            decodeURIComponent(queryParams.headerName) || "页眉"
          } </span>
        </div>`;
      // 页尾模板， 详情查看 http://puppeteerjs.com/#?product=Puppeteer&version=v19.2.2&show=api-pagepdfoptions
      const footer = `
      <div style="width:calc(100% - 28px);margin-bottom: -18px; height:40px;border-top:1px solid #c9c9c9; display: flex;align-items: center;justify-content: center;color: #999999;">
        <span class="pageNumber" style="color: #4e87fc; font-size: 14px;"></span>
        <span style="color: #999999; font-size: 14px;">/</span>
        <span class="totalPages" style="color: #999999; font-size: 14px;"></span>
      </div>`;
      // PDF尺寸设置
      const pdfConfig = {
        //纸张尺寸
        format: "A4",
        //打印背景,默认为false
        //printBackground: true,
        /*  width: '1300px',
         height: '1848px', */
        //不展示页眉
        margin: {
          top: 40,
          bottom: 40,
          left: "0",
          right: "0",
        },
        /* format: {
          width: 550
        }, */
        // scale: 0.99,
        displayHeaderFooter: true, // 是否展示页头页脚
        preferCSSPageSize: true, // 页面优先级声明CSS
        printBackground: true, // 是否打印背景，CSS
        footerTemplate: footer, // 页尾模板
        headerTemplate: header, // 页眉模板 /* (await axios.get('http://localhost:3000/header')).data */
        timeout: 0,
      };

      await page2.addStyleTag({
        content: "@page { size: 1200px 1698px; }", // 设置页面高度和宽度
      });
      const result = await page2.pdf(pdfConfig); // 生成 PDF
      const endTime = dayjs(); // 获取结束时间
      console.log(`生成时间： ${endTime.diff(startTime, "second", true)}s`); // 生成耗时
      let filePath = path.resolve(
        __dirname,
        `../static/${dayjs().format("YYYY_MM_DD_HH_mm_ss考试报告")}.pdf`
      );
      // fs.writeFileSync(filePath, result); // 写入文件

      // 假设文件路径
      // const filePath2 = path.join(filePath); // 确保文件存在
      // console.log("result", result);

      await page2.close(); // 关闭标签页
      --handlingCount;
      // 使用fs.createReadStream创建文件的可读流
      // const stream = fs.createReadStream(filePath2);

      // 将Buffer转换为可读流
      const readable = new Stream.Readable({
        read() {
          this.push(Buffer.from(result));
          this.push(null); // 表示流的结束
        },
      });
      // 设置响应类型，根据你的文件类型更改，比如'application/pdf'
      ctx.set("Content-Type", "application/pdf");
      // 将文件流作为响应体返回
      ctx.body = readable;
    }
    // 超过最大处理任务则返回提示
    else {
      --handlingCount;
      ctx.body = {
        data: null,
        status: 502,
        message: "当前人数过多，请稍后再尝试",
      };
    }
  } catch (error) {
    --handlingCount;
    console.warn(error);

    ctx.body = {
      data: null,
      status: 502,
      message: "当前人数过多，请稍后再尝试",
    };
  }
}

module.exports = {
  launchBrowser,
  getNewPage,
  eventHandler,
};
